package biz

import (
	"context"

	byoneconfig "code.bydev.io/cht/customer/kyc_admin_service/internal/config"
	"code.bydev.io/cht/customer/kyc_admin_service/internal/domain/kyc"
	"code.bydev.io/cht/customer/kyc_admin_service/internal/pkg/kycadminapi"
	"code.bydev.io/cht/customer/kyc_admin_service/internal/utils/urpc/private"
	"code.bydev.io/frameworks/byone/core/logx"
	"code.bydev.io/frameworks/byone/kafka"
	"code.bydev.io/frameworks/sechub-go/api"
	"git.bybit.com/svc/go/pkg/bdal"
	"git.bybit.com/svc/go/pkg/benv"
	"git.bybit.com/svc/go/pkg/bmetric"
)

var _envHeader *Environment

func InitEnvironment(ctx context.Context, c byoneconfig.Config) (*Environment, error) {
	logger := provideLogger()
	environment := provideBEnv(ctx, logger)
	// metric
	bmetricEnvironment := provideMetricEnv(environment)
	// 告警
	teller := provideTeller(logger, provideLarkRaiser())
	// kyc admin sechub
	kycAdminSechub, err := provideKycAdminSecHub()
	if err != nil {
		return nil, err
	}
	logx.Info("provideKycAdminSecHub init success")
	// kyc public sechub
	bizKycSecHubWrapper, err := provideKycSecHub()
	if err != nil {
		return nil, err
	}
	logx.Info("provideKycSecHub init success")
	// kycAdminDB
	bizChtKycDBWrapper, err := provideChtKycDB(environment, c.NothingKycAdminDB)
	if err != nil {
		return nil, err
	}
	logx.Info("provideChtKycDB init success")
	// InverseDB
	bizUserDBWrapper, err := provideUserDB(environment, c.NothingInverseDB)
	if err != nil {
		return nil, err
	}
	logx.Info("provideUserDB init success")

	messageQueue := provideKafka(c.KycAdminProducer)

	// 初始化RPC服务
	rpcClient := private.InitRPC(c.RPC)
	// kyc服务
	kycSvc := provideKycServiceGRPC(rpcClient)
	logx.Info("provideKycServiceGRPC init success")

	// aws kms加解密
	session, err := provideAWSSession()
	if err != nil {
		return nil, err
	}
	logx.Info("provideAWSSession init success")
	internalDataKey, err := provideInternalDataKey(provideKMS(session))
	if err != nil {
		return nil, err
	}
	logx.Info("provideInternalDataKey init success")

	// 初始化Environment
	_envHeader = &Environment{
		Environment:     environment,
		metric:          bmetricEnvironment,
		tlr:             teller,
		secHub:          kycAdminSechub,
		kycSecHub:       bizKycSecHubWrapper,
		messageQueue:    messageQueue,
		chtKycDB:        bizChtKycDBWrapper,
		userDB:          bizUserDBWrapper,
		kycSvc:          kycSvc,
		internalDataKey: internalDataKey,
	}
	return _envHeader, err
}

// Env 全局资源实例
func Env() *Environment {
	return _envHeader
}

// Environment 管理生命周期为完整服务进程的资源
// 例如连接池、配置等
type Environment struct {
	*benv.Environment

	metric          *bmetric.Environment
	tlr             kycadminapi.Teller
	secHub          *api.Sechub
	kycSecHub       kycSecHubWrapper
	chtKycDB        chtKycDBWrapper
	userDB          userDBWrapper
	messageQueue    kafka.Producer
	kycSvc          kyc.KycSvc
	internalDataKey InternalDataKey
}

func (env *Environment) WithContext(ctx context.Context) *Environment {
	next := new(Environment)
	*next = *env
	next.Environment = next.Environment.WithContext(ctx)

	return next
}

func (env *Environment) handleTimeSummary(method string) bmetric.Summary {
	return env.metric.Summary("handle_time_sec", "time elapsed to handle an rpc call", bmetric.Labels{
		"method": method,
	})
}

func (env *Environment) Teller() kycadminapi.Teller {
	return env.tlr
}

func (env *Environment) SecHub() *api.Sechub {
	return env.secHub
}

func (env *Environment) KycSecHub() *api.Sechub {
	return env.kycSecHub.secHub
}

func (env *Environment) ChtKycDB() *bdal.Environment {
	return env.chtKycDB.Environment
}

func (env *Environment) UserDB() *bdal.Environment {
	return env.userDB.Environment
}

func (env *Environment) KycSvc() kyc.KycSvc {
	return env.kycSvc
}

func (env *Environment) InternalDataKey() InternalDataKey {
	return env.internalDataKey
}

func (env *Environment) Kafka() kafka.Producer {
	return env.messageQueue
}
